package com.learn.netty.nio.groupchat;

import lombok.extern.slf4j.Slf4j;
import org.springframework.expression.spel.ast.Selection;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 1. 上下线功能
 * 2. 群发消息
 * 3.
 * @author zhongshitao
 * @date 2020/10/19 5:32 下午
 */
@Slf4j
public class GroupSystemServer {

    private Selector selector;

    private ServerSocketChannel serverSocketChannel;

    private static final int PORT = 6669;

    private String USERNAME;


    public GroupSystemServer() {
        try {
            selector = Selector.open();
            serverSocketChannel = ServerSocketChannel.open();
            serverSocketChannel.socket().bind(new InetSocketAddress(PORT));
            serverSocketChannel.configureBlocking(false);
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }

    /**
     * 监听端口服务
     */
    private void listen() {
        while (true) {
            try {
//                log.info("---------服务器监听已启动，端口:{}--------", PORT);
                int listenNums = selector.select();
                if (listenNums > 0) {
                    Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
                    while (keyIterator.hasNext()) {
                        SelectionKey currentEvent = keyIterator.next();
                        // 客户端连接服务器
                        if (currentEvent.isAcceptable()) {
                            SocketChannel socketChannel = serverSocketChannel.accept();
                            socketChannel.configureBlocking(false);
                            log.info(socketChannel.getRemoteAddress() + " 已上线...");
                            socketChannel.register(selector, SelectionKey.OP_READ);
                        }

                        // 客户端写入内容
                        if (currentEvent.isReadable()) {
                            SocketChannel channel = (SocketChannel) currentEvent.channel();
                            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                            int readNum = channel.read(byteBuffer);
                            if (readNum > 0) {
                                String receiveMessage = new String(byteBuffer.array()).trim();
                                String message = String.format("%s 说：%s",
                                        channel.getRemoteAddress(), receiveMessage);
                                log.info("服务器接收消息[{}]: {}", new SimpleDateFormat("YYYY-MM-dd HH:mm:ss").format(new Date()), message);
                                sendInfo(message, channel);
                            }

                        }
                        // 删除本次触发事件
                        keyIterator.remove();
                    }
                }
            } catch (Exception e) {
                log.info("用户：{} 已下线", USERNAME);

            }
        }
    }

    /**
     * 给其他客户端发送消息
     * @param msg
     * @param self
     */
    private void sendInfo(String msg, SocketChannel self) throws IOException {
        Set<SelectionKey> selectionKeys = selector.keys();

        for (SelectionKey selectionKey : selectionKeys) {
            SelectableChannel channel = selectionKey.channel();
            if (channel instanceof SocketChannel && channel != self) {
                ByteBuffer writeBuffer = ByteBuffer.wrap(msg.getBytes());
                ((SocketChannel) channel).write(writeBuffer);
            }
        }
    }



    public static void main(String[] args) {
        try {
            GroupSystemServer groupSystemServer = new GroupSystemServer();
            groupSystemServer.listen();
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        }
    }
}
